#include <QtGui>
#include "mainwindow.h"

#include "dialog/dlgfractal.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    workspace = new QWorkspace;
    setCentralWidget(workspace);

    createActions();
    createMenus();
    createToolBars();
    updateIO();
    createStatusBar();
    createDockWidget();
    setWindowTitle(tr("Lab"));

    connect(workspace, SIGNAL(windowActivated(QWidget *)),
            this, SLOT(updateIO()));

    windowMapper = new QSignalMapper(this);
    connect(windowMapper, SIGNAL(mapped(QWidget*)),
            this, SLOT(setActiveSubWindow(QWidget*)));
}

MainWindow::~MainWindow()
{
    
}

void MainWindow::createActions()
{
    actNew = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
    actNew->setShortcuts(QKeySequence::New);
    actNew->setStatusTip(tr("Create a new file"));
    connect(actNew, SIGNAL(triggered()), this, SLOT(newFile()));

    actOpen = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
    actOpen->setShortcuts(QKeySequence::Open);
    actOpen->setStatusTip(tr("Open an existing file"));
    connect(actOpen, SIGNAL(triggered()), this, SLOT(open()));

    actSave = new QAction(QIcon(":/images/save.png"), tr("&Save"), this);
    actSave->setShortcuts(QKeySequence::Save);
    actSave->setStatusTip(tr("Save the document to disk"));
    connect(actSave, SIGNAL(triggered()), this, SLOT(save()));

//    saveAsAct = new QAction(tr("Save &As..."), this);
//    saveAsAct->setShortcuts(QKeySequence::SaveAs);
//    saveAsAct->setStatusTip(tr("Save the document under a new name"));
//    connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));

//! [0]
    actExit = new QAction(tr("E&xit"), this);
    actExit->setShortcuts(QKeySequence::Quit);
    actExit->setStatusTip(tr("Exit the application"));
    connect(actExit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
//! [0]

    actFractal = new QAction(QIcon(":/images/flake.png"), tr("Fractal"), this);
    actFractal->setStatusTip(tr("Generate fractal"));
    connect(actFractal, SIGNAL(triggered()), this, SLOT(genFractal()));

    createCSGActions();

    actViewReset = new QAction(QIcon(":/images/reset.png"), tr("Reset"), this);
    actViewReset->setStatusTip(tr("Reset view"));

    actViewLight = new QAction(QIcon(":/images/light.png"), tr("Light"), this);
    actViewLight->setStatusTip(tr("Enable lighting"));
    actViewLight->setCheckable(true);
    actViewLight->setChecked(false);
    connect(actViewLight, SIGNAL(triggered()), this, SLOT(enableLighting()));

    for (int i = 0; i < MATERIAL_END; i++)
    {
        actViewMaterial[i] = new QAction(materialName[i], this);
        actViewMaterial[i]->setCheckable(true);
        actViewMaterial[i]->setChecked(false);
        connect(actViewMaterial[i], SIGNAL(triggered()), this, SLOT(changeMaterial()));
    }
    actViewMaterial[3]->setChecked(true);

    actClose = new QAction(tr("Cl&ose"), this);
    actClose->setStatusTip(tr("Close the active window"));
    connect(actClose, SIGNAL(triggered()),
            workspace, SLOT(closeActiveWindow()));

    actCloseAll = new QAction(tr("Close &All"), this);
    actCloseAll->setStatusTip(tr("Close all the windows"));
    connect(actCloseAll, SIGNAL(triggered()),
            workspace, SLOT(closeAllWindows()));

    actTile = new QAction(tr("&Tile"), this);
    actTile->setStatusTip(tr("Tile the windows"));
    connect(actTile, SIGNAL(triggered()), workspace, SLOT(tile()));

    actCascade = new QAction(tr("&Cascade"), this);
    actCascade->setStatusTip(tr("Cascade the windows"));
    connect(actCascade, SIGNAL(triggered()), workspace, SLOT(cascade()));

    actNext = new QAction(tr("Ne&xt"), this);
    actNext->setShortcuts(QKeySequence::NextChild);
    actNext->setStatusTip(tr("Move the focus to the next window"));
    connect(actNext, SIGNAL(triggered()),
            workspace, SLOT(activateNextWindow()));

    actPrevious = new QAction(tr("Pre&vious"), this);
    actPrevious->setShortcuts(QKeySequence::PreviousChild);
    actPrevious->setStatusTip(tr("Move the focus to the previous "
                                 "window"));
    connect(actPrevious, SIGNAL(triggered()),
            workspace, SLOT(activatePreviousWindow()));

    actExit = new QAction(tr("E&xit"), this);

    actExit->setShortcut(tr("Ctrl+Q"));

    actExit->setStatusTip(tr("Exit the application"));

    connect(actExit, SIGNAL(triggered()),
            qApp, SLOT(closeAllWindows()));

    actSeparator = new QAction(this);
    actSeparator->setSeparator(true);

    actAbout = new QAction(tr("&About"), this);
    actAbout->setStatusTip(tr("Show the application's About box"));
    connect(actAbout, SIGNAL(triggered()), this, SLOT(about()));

    actAboutQt = new QAction(tr("About &Qt"), this);
    actAboutQt->setStatusTip(tr("Show the Qt library's About box"));
    connect(actAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}

void MainWindow::createMenus()
{
    menuFile = menuBar()->addMenu(tr("&File"));
    menuFile->addAction(actNew);
    menuFile->addAction(actOpen);
    menuFile->addAction(actSave);
//    fileMenu->addAction(saveAsAct);
    menuFile->addSeparator();
    QAction *action = menuFile->addAction(tr("Switch layout direction"));
    connect(action, SIGNAL(triggered()), this, SLOT(switchLayoutDirection()));
    menuFile->addAction(actExit);

    menuEdit = menuBar()->addMenu(tr("&Edit"));
    menuEdit->addSeparator();

    /*editMenu->addAction(cutAct);
    editMenu->addAction(copyAct);
    editMenu->addAction(pasteAct)*/;

    menuView = menuBar()->addMenu(tr("&View"));


    // connect(viewMenu, SIGNAL(aboutToShow()), this, SLOT(updateViewMenu()));
    connect(workspace, SIGNAL(windowActivated(QWidget*)), this, SLOT(updateViewMenu()));

    actSeparator = new QAction(this);
    actSeparator->setSeparator(true);

    menuView->addAction(actSeparator);

    menuView->addAction(actViewLight);

    menuViewMaterial = menuView->addMenu(tr("Change Material"));
    actMatGp = new QActionGroup(this);
    for (int i = 0; i < MATERIAL_END; i++)
    {
        menuViewMaterial->addAction(actMatGp->addAction(actViewMaterial[i]));
    }

    menuWindow = menuBar()->addMenu(tr("&Window"));
    updateWindowMenu();
    connect(menuWindow, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu()));

    menuBar()->addSeparator();

    menuHelp = menuBar()->addMenu(tr("&Help"));
    menuHelp->addAction(actAbout);
    menuHelp->addAction(actAboutQt);
}

void MainWindow::updateIO()
{
    bool hasGLChild = (activeGLChild() != 0);
    actSave->setEnabled(hasGLChild);

    actViewReset->setEnabled(hasGLChild);
    actViewLight->setEnabled(hasGLChild);
    for (int i = 0; i < MATERIAL_END; i++)
    {
        actViewMaterial[i]->setEnabled(hasGLChild);
    }
    // saveAsAct->setEnabled(hasGLChild);
    // pasteAct->setEnabled(hasGLChild);
    actSeparator->setVisible(hasGLChild);

    toolBarCSG->hide();
    toolBarFractal->hide();
    GLChild * child = activeGLChild();

    if (!child)
    {
        return;
    }
    else if (typeid(*child) == typeid(GLChildCSG))
    {
        toolBarCSG->show();
    }
    else if (typeid(*child) == typeid(GLChildFractal))
    {
        toolBarFractal->show();
    }
    else
    {

    }

    // bool hasSelection = (activeGLChild());
    // cutAct->setEnabled(hasSelection);
    // copyAct->setEnabled(hasSelection);

}

void MainWindow::createToolBars()
{
    toolBarFile = addToolBar(tr("File"));
    toolBarFile->addAction(actNew);
    toolBarFile->addAction(actOpen);
    toolBarFile->addAction(actSave);

//    toolBarEdit = addToolBar(tr("Edit"));
//    editToolBar->addAction(cutAct);
//    editToolBar->addAction(copyAct);
//    editToolBar->addAction(pasteAct);

    toolBarView = addToolBar(tr("View"));
    toolBarView->addAction(actViewReset);
    toolBarView->addAction(actViewLight);

    toolBarCSG = addToolBar(tr("CSG"));
    toolBarCSG->addAction(actCSGNaive);

    toolBarCSG->hide();

    toolBarFractal = addToolBar(tr("Fractal"));
    toolBarFractal->addAction(actFractal);

    toolBarFractal->hide();
}

void MainWindow::createStatusBar()
{
    labelRunStatus = new QLabel("ready");
    labelRunStatus->setAlignment(Qt::AlignRight);
    statusBar()->addWidget(labelRunStatus, 1);
    statusBar()->showMessage(tr("Ready"));
}

void MainWindow::updateWindowMenu()
{
    menuWindow->clear();
    menuWindow->addAction(actClose);
    menuWindow->addAction(actCloseAll);
    menuWindow->addSeparator();
    menuWindow->addAction(actTile);
    menuWindow->addAction(actCascade);
    menuWindow->addSeparator();
    menuWindow->addAction(actNext);
    menuWindow->addAction(actPrevious);
    menuWindow->addAction(actSeparator);

    QList<QWidget *> windows = workspace->windowList();
    actSeparator->setVisible(!windows.isEmpty());

    for (int i = 0; i < windows.size(); ++i) {
        GLChild *child = qobject_cast<GLChild *>(windows.at(i));

        QString text;
        if (i < 9) {
            text = tr("&%1 %2").arg(i + 1)
                               .arg(child->userFriendlyCurrentFile());
        } else {
            text = tr("%1 %2").arg(i + 1)
                              .arg(child->userFriendlyCurrentFile());
        }
        QAction *action  = menuWindow->addAction(text);
        action->setCheckable(true);
        action->setChecked(child == workspace->activeWindow());
        connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));
                windowMapper->setMapping(action, windows.at(i));
    }
}

void MainWindow::genFractal()
{
    DlgFractal dlg(this);

    if (dlg.exec() == QDialog::Accepted)
    {

    }
}

void MainWindow::drawCSGNaively()
{
}

void MainWindow::createDockWidget()
{
    //设置第二个QDockWidget
    dockWidgetOutput = new QDockWidget(this);
    dockWidgetOutput->setWindowTitle(tr("Output"));
    dockWidgetOutput->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::BottomDockWidgetArea);
    editOutput = new QTextEdit(tr("Output"));
    dockWidgetOutput->setWidget(editOutput);

    this->addDockWidget(Qt::BottomDockWidgetArea, dockWidgetOutput);
    //向菜单和工具栏中添加第一个QDockWidget的显示和隐藏动作
    menuView->addAction(dockWidgetOutput->toggleViewAction());

    dockWidgetOutput->toggleViewAction()->setIcon(QIcon(":/images/output.png"));
    toolBarView->addAction(dockWidgetOutput->toggleViewAction());
}

void MainWindow::createCSGActions()
{
    actCSGNaive = new QAction(QIcon(":/images/open.png"), tr("&Naive"), this);
    actCSGNaive->setStatusTip(tr("Draw Naively"));
    connect(actCSGNaive, SIGNAL(triggered()), this, SLOT(drawCSGNaively()));
}

void MainWindow::updateViewMenu()
{
    GLChild * win = qobject_cast<GLChild *>(workspace->activeWindow());

    if (win)
    {
        actViewLight->setChecked(win->getLightingFlag());
    }
}

GLChildCSG *MainWindow::createGLChild()
{
    GLChildCSG *child = GLChildFactory::createChildCSG();
    workspace->addWindow(child);

//    connect(child, SIGNAL(copyAvailable(bool)),
//            cutAct, SLOT(setEnabled(bool)));
//    connect(child, SIGNAL(copyAvailable(bool)),
//            copyAct, SLOT(setEnabled(bool)));

    return child;
}

void MainWindow::newFile()
{
    GLChild *win = GLChildFactory::createChildFractal();
    workspace->addWindow(win);
    win->show();

    ((GLChildFractal*)win)->generate();

//    GLChild * win = qobject_cast<GLChild *>(workspace->activeWindow());
//    if (win)
//    {
//        win->resetView();
//    }
}

void MainWindow::open()
{
    QString fileName = QFileDialog::getOpenFileName(this);
    if (!fileName.isEmpty()) {
        GLChildCSG *child = createGLChild();
        if (child->loadFile(fileName)) {
            statusBar()->showMessage(tr("File loaded"), 2000);
            child->show();
        } else {
            child->close();
        }
    }
}

void MainWindow::save()
{
    if (activeGLChild() && activeGLChild()->save())
        statusBar()->showMessage(tr("File saved"), 2000);
}

void MainWindow::saveAs()
{
    if (activeGLChild() && activeGLChild()->saveAs())
        statusBar()->showMessage(tr("File saved"), 2000);
}

void MainWindow::cut()
{
}

void MainWindow::copy()
{
}

void MainWindow::paste()
{
}

void MainWindow::about()
{
    QMessageBox::about(this, tr("About MDI"),
             tr("The <b>MDI</b> example demonstrates how to write multiple "
                "document interface applications using Qt."));
}

GLChild *MainWindow::activeGLChild()
{
    if (QWidget *activeSubWindow = workspace->activeWindow())
        return qobject_cast<GLChild *>(activeSubWindow);
    return 0;
}
